package com.xhwl.centiotdata.handler.account.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.handler.account.AccountFactory;
import com.xhwl.centiotdata.handler.account.AccountHandler;
import com.xhwl.centiotdata.handler.pedestrian.impl.PedestrianIntegrationMiLiHandler;
import com.xhwl.centiotdata.pojo.dto.mili.TenementMiLiDTO;
import com.xhwl.centiotdata.pojo.dto.mili.WorkerMiLiDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationPropertiesDTO;
import com.xhwl.centiotdata.service.cent.IAccountCentService;
import com.xhwl.centiotdata.service.cent.IAuthAccountCentService;
import com.xhwl.centiotdata.service.cent.IOrganizationService;
import com.xhwl.centiotdata.service.cent.IResidentInfoService;
import com.xhwl.centiotdata.suppliersystem.mili.PedestrianMiLiHandler;
import com.xhwl.centiotdata.utils.Base64Utils;
import com.xhwl.common.dto.cent.sdata.AccountDTO;
import com.xhwl.common.enums.ProductEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.cent.auth.AuthAccountMapping;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.pojo.cent.sdata.Organization;
import com.xhwl.common.pojo.cent.sdata.Room;
import com.xhwl.common.pojo.cent.sdata.personnel.StaffDTO;
import com.xhwl.common.query.cent.sdata.RoomQuery;
import com.xhwl.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: wuyuhao
 * @createDate: 2022/10/20 13:51
 */
@Service
@Slf4j
public class AccountMiLiHandler extends AccountHandler {

    @Resource
    private IAuthAccountCentService iAuthPedestrianCentService;

    @Autowired
    private PedestrianMiLiHandler pedestrianMiLiHandler;

    @Autowired
    private PedestrianIntegrationMiLiHandler pedestrianIntegrationMiLiHandler;

    @Resource
    private IAccountCentService iAccountCentService;

    @Autowired
    private IResidentInfoService iResidentInfoService;

    @Autowired
    private IOrganizationService iOrganizationService;


    @Override
    public void afterPropertiesSet() throws Exception {
        // 米立人行
        AccountFactory.register(ProductEnum.MILI_PEDESTRIAN.getId(), this);
    }

    @Override
    public void add(StaffDTO dto, Integer projectId, DeviceProjSupplierCategory config) {
        this.handleAdd(dto, projectId, config);
    }

    @Override
    public void update(StaffDTO dto, Integer projectId, DeviceProjSupplierCategory config) {
        // 查询关联表
        AuthAccountMapping authAccount = iAuthPedestrianCentService.query(projectId, dto.getAccountId(), config.getProductId());
        //没查到关联关系，则新增
        if (null == authAccount) {
            this.handleAdd(dto, projectId, config);
        } else {
            this.handleUpdate(dto, config);
        }
    }

    @Override
    public void delete(AccountDTO dto, Integer projectId, DeviceProjSupplierCategory config) {
        if (null != config) {
            JSONObject properties = config.getProperties();
            PedestrianIntegrationPropertiesDTO propertiesDTO = JSON.toJavaObject(properties, PedestrianIntegrationPropertiesDTO.class);
            PedestrianIntegrationConfigDTO configDTO = new PedestrianIntegrationConfigDTO();
            BeanUtils.copyProperties(propertiesDTO, configDTO);
            configDTO.setProductId(config.getProductId());
            configDTO.setProjectId(config.getProjectId());

            //查询关联表
            AuthAccountMapping authAccount = iAuthPedestrianCentService.query(projectId, dto.getId(), config.getProductId());
            if (null != authAccount) {
                List<Organization> organizationList = iResidentInfoService.getOrgListByAccountId(String.valueOf(dto.getId()), config.getProjectId());
                if (ObjectUtils.isEmpty(organizationList)) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("GuardID", authAccount.getOpenId());
                    boolean delWorker = pedestrianMiLiHandler.delWorker(configDTO, map);
                    if (!delWorker) {
                        throw new BusinessException("删除米立工作人员信息失败！");
                    }
                } else {
                    log.info("需要删除的人员第三方id：{}", authAccount.getOpenId());
                    List<String> users = Arrays.asList(authAccount.getOpenId().split(","));
                    for(String s : users) {
                        String openId = Arrays.asList(s.split("_")).get(1);
                        Map<String, Object> map = new HashMap<>();
                        map.put("ID", openId);
                        boolean delTenement = pedestrianMiLiHandler.delTenement(configDTO, map);
                        if (!delTenement) {
                            throw new BusinessException("删除米立住户信息失败！");
                        }
                    }
                }
                iAuthPedestrianCentService.deleteAccountMapping(projectId, dto.getId(), authAccount.getOpenId(), config.getProductId());
            }
        }
    }

    private void handleAdd(StaffDTO dto, Integer projectId, DeviceProjSupplierCategory config) {
        if (null != config) {
            try {
                JSONObject properties = config.getProperties();
                PedestrianIntegrationPropertiesDTO propertiesDTO = JSON.toJavaObject(properties, PedestrianIntegrationPropertiesDTO.class);
                PedestrianIntegrationConfigDTO configDTO = new PedestrianIntegrationConfigDTO();
                BeanUtils.copyProperties(propertiesDTO, configDTO);
                configDTO.setProductId(config.getProductId());
                configDTO.setProjectId(config.getProjectId());

                Integer accountId = dto.getAccountId();
                Account account = iAccountCentService.findById(accountId);
                List<Organization> organizationList = iResidentInfoService.getOrgListByAccountId(String.valueOf(accountId), config.getProjectId());
                long id;
                List<String> openIdList = new ArrayList<>();
                if (ObjectUtils.isEmpty(organizationList)) {
                    WorkerMiLiDTO workerMiLiDTO = this.handleWorkerInfo(account);
                    log.info("workerMiLiDTO: {}", workerMiLiDTO);
                    WorkerMiLiDTO addWorker = pedestrianMiLiHandler.addWorker(configDTO, workerMiLiDTO);
                    if (ObjectUtils.isEmpty(addWorker)) {
                        throw new BusinessException("添加米立工作人员失败！");
                    } else {
                        id = addWorker.getGuardID();
                        openIdList.add(String.valueOf(id));
                        // 工作人员添加人脸
                        if (StringUtils.isNotEmpty(account.getFaceUrl())) {
                            Map<String, Object> map = new HashMap<>();
                            map.put("ID", id);
                            // 1：住户（默认）；2：工作人员
                            map.put("PersonType", 2);
                            map.put("Photo", "data:image/jpeg;base64," + Base64Utils.imageUrlToBase64(account.getFaceUrl()));
                            pedestrianMiLiHandler.addFace(configDTO, map);
                        }
                    }
                } else {
                    List<Integer> orgIdList = organizationList.stream().map(Organization::getId).collect(Collectors.toList());
                    RoomQuery roomQuery = new RoomQuery();
                    roomQuery.setOrgIds(orgIdList);
                    roomQuery.setProjectId(configDTO.getProjectId());
                    List<Room> roomList = iOrganizationService.list(roomQuery);
                    for(Room room : roomList) {
                        TenementMiLiDTO tenementMiLiDTO = this.handleResidentInfo(account, room);
                        Map<String, Object> map = new HashMap<>();
                        map.put("FrameNo", tenementMiLiDTO.getFrameNo());
                        List<TenementMiLiDTO> tenementMiLiDTOList = pedestrianMiLiHandler.queryTenement(configDTO, map);
                        // 当该房间下面有用户，表示已经有业主了，需要手动指定其与业主的关系
                        if (!tenementMiLiDTOList.isEmpty()) {
                            tenementMiLiDTO.setRelationshipDesc("其他");
                        }
                        log.info("tenementMiLiDTO: {}", tenementMiLiDTO);
                        TenementMiLiDTO addTenement = pedestrianMiLiHandler.addTenement(configDTO, tenementMiLiDTO);
                        if (ObjectUtils.isEmpty(addTenement)) {
                            throw new BusinessException("添加米立住户失败！");
                        } else {
                            id = addTenement.getID();
                            // 用房间号拼接上住户id，例如 02011703_1
                            openIdList.add(addTenement.getFrameNo() + "_" + id);
                            // 住户添加人脸
                            if (StringUtils.isNotEmpty(account.getFaceUrl())) {
                                map.clear();
                                map.put("ID", id);
                                // 1：住户（默认）；2：工作人员
                                map.put("PersonType", 1);
                                map.put("Photo", "data:image/jpeg;base64," + Base64Utils.imageUrlToBase64(account.getFaceUrl()));
                                pedestrianMiLiHandler.addFace(configDTO, map);
                            }
                        }
                    }
                }
                // 中台这边一个住户，对应米立可能有多个住户id，在米立平台，一个住户只能绑定一个房屋，如果有多个房屋，需要新增多个住户去绑定。工作人员不会有这种情况
                // 比如01房有个张三，02房也有个张三，虽然是同一个人，但是他们id是不一样的，所以第三方id使用：房间号 + "_" + id，然后用逗号拼接成一个字符串，如："01010101_1,02010101_2"
                String openId = String.join(",", openIdList);
                //保存人员id关联表
                boolean saveAuthResult = iAuthPedestrianCentService.save(projectId, accountId,
                        openId, null, config.getProductId());
                log.info("米立账号关联关系保存结果 : {}", saveAuthResult);
            } catch (Exception e) {
                log.error("账号信息：{}", dto);
                log.error("配置信息：{}", config);
                log.error("同步米立平台异常", e);
            }
        }
    }

    private void handleUpdate(StaffDTO dto, DeviceProjSupplierCategory config) {
        if (null != config) {
            try {
                JSONObject properties = config.getProperties();
                PedestrianIntegrationPropertiesDTO propertiesDTO = JSON.toJavaObject(properties, PedestrianIntegrationPropertiesDTO.class);
                Integer projectId = config.getProjectId();
                Integer productId = config.getProductId();
                PedestrianIntegrationConfigDTO configDTO = new PedestrianIntegrationConfigDTO();
                BeanUtils.copyProperties(propertiesDTO, configDTO);
                configDTO.setProductId(productId);
                configDTO.setProjectId(projectId);

                Integer accountId = dto.getAccountId();
                // 先删除关联，再新增
                AccountDTO accountDTO = new AccountDTO();
                accountDTO.setId(accountId);
                this.delete(accountDTO, projectId, config);
                this.handleAdd(dto, projectId, config);
            } catch (Exception e) {
                log.error("账号信息：{}", dto);
                log.error("配置信息：{}", config);
                log.error("同步米立平台异常", e);
            }
        }
    }

    private WorkerMiLiDTO handleWorkerInfo(Account account) {
        WorkerMiLiDTO workerMiLiDTO = new WorkerMiLiDTO();
        workerMiLiDTO.setGuardID(-1);
        if (!ObjectUtils.isEmpty(account.getName())) {
            workerMiLiDTO.setName(account.getName());
        } else {
            workerMiLiDTO.setName("工作人员");
        }
        if (!ObjectUtils.isEmpty(account.getPhone())) {
            workerMiLiDTO.setTelephone(account.getPhone());
        } else {
            throw new BusinessException("没有电话号码！");
        }
        if (!ObjectUtils.isEmpty(account.getSex())) {
            if (account.getSex() == 0) {
                workerMiLiDTO.setGender("2");
            } else if (account.getSex() == 1) {
                workerMiLiDTO.setGender("1");
            } else {
                workerMiLiDTO.setGender("0");
            }
        } else {
            workerMiLiDTO.setGender("0");
        }
        workerMiLiDTO.setCredentialType("111");
        return workerMiLiDTO;
    }

    private TenementMiLiDTO handleResidentInfo(Account account, Room room) {
        TenementMiLiDTO tenementMiLiDTO = new TenementMiLiDTO();
        // 中台创建房间时，需手动填写编码，保持与米立平台房间框架编码一致
        String frameNO = room.getCode();
        if (ObjectUtils.isEmpty(frameNO)) {
            throw new BusinessException("米立该框架不存在！");
        } else {
            tenementMiLiDTO.setFrameNo(frameNO);
        }

        tenementMiLiDTO.setID(-1);
        if (!ObjectUtils.isEmpty(account.getName())) {
            tenementMiLiDTO.setName(account.getName());
        } else {
            tenementMiLiDTO.setName(frameNO);
        }
        if (!ObjectUtils.isEmpty(account.getPhone())) {
            tenementMiLiDTO.setTelephone(account.getPhone());
            tenementMiLiDTO.setTelephone2(account.getPhone());
        } else {
            throw new BusinessException("没有电话号码！");
        }
        if (!ObjectUtils.isEmpty(account.getSex())) {
            if (account.getSex() == 0) {
                tenementMiLiDTO.setGender("2");
            } else if (account.getSex() == 1) {
                tenementMiLiDTO.setGender("1");
            } else {
                tenementMiLiDTO.setGender("0");
            }
        } else {
            tenementMiLiDTO.setGender("0");
        }
        tenementMiLiDTO.setCredentialType("111");
        return tenementMiLiDTO;
    }
}
